home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH4 / SRC / MAKEGRAY.FRM (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1997-01-03  |  15.5 KB  |  485 lines

  1. VERSION 4.00
  2. Begin VB.Form MakeGrayForm 
  3.    Caption         =   "Make Gray"
  4.    ClientHeight    =   4095
  5.    ClientLeft      =   1320
  6.    ClientTop       =   1350
  7.    ClientWidth     =   4695
  8.    Height          =   4785
  9.    Left            =   1260
  10.    LinkTopic       =   "Form1"
  11.    ScaleHeight     =   273
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   313
  14.    Top             =   720
  15.    Width           =   4815
  16.    Begin VB.PictureBox FromSwin 
  17.       Height          =   3855
  18.       Left            =   0
  19.       ScaleHeight     =   253
  20.       ScaleMode       =   3  'Pixel
  21.       ScaleWidth      =   293
  22.       TabIndex        =   2
  23.       Top             =   0
  24.       Width           =   4455
  25.       Begin VB.PictureBox FromPict 
  26.          AutoRedraw      =   -1  'True
  27.          AutoSize        =   -1  'True
  28.          Height          =   1905
  29.          Left            =   0
  30.          ScaleHeight     =   123
  31.          ScaleMode       =   3  'Pixel
  32.          ScaleWidth      =   88
  33.          TabIndex        =   3
  34.          Top             =   0
  35.          Width           =   1380
  36.       End
  37.    End
  38.    Begin VB.HScrollBar FromHBar 
  39.       Enabled         =   0   'False
  40.       Height          =   255
  41.       Left            =   0
  42.       TabIndex        =   1
  43.       Top             =   3840
  44.       Width           =   4485
  45.    End
  46.    Begin VB.VScrollBar FromVBar 
  47.       Enabled         =   0   'False
  48.       Height          =   3855
  49.       Left            =   4440
  50.       TabIndex        =   0
  51.       Top             =   0
  52.       Width           =   255
  53.    End
  54.    Begin MSComDlg.CommonDialog FileDialog 
  55.       Left            =   4200
  56.       Top             =   3600
  57.       _Version        =   65536
  58.       _ExtentX        =   847
  59.       _ExtentY        =   847
  60.       _StockProps     =   0
  61.       CancelError     =   -1  'True
  62.    End
  63.    Begin VB.Menu mnuFile 
  64.       Caption         =   "&File"
  65.       Begin VB.Menu mnuFileLoad 
  66.          Caption         =   "&Load..."
  67.          Shortcut        =   ^L
  68.       End
  69.       Begin VB.Menu mnuFileSep2 
  70.          Caption         =   "-"
  71.       End
  72.       Begin VB.Menu mnuFileExit 
  73.          Caption         =   "E&xit"
  74.       End
  75.    End
  76. Attribute VB_Name = "MakeGrayForm"
  77. Attribute VB_Creatable = False
  78. Attribute VB_Exposed = False
  79. Option Explicit
  80. Dim SysPalSize As Integer
  81. Dim NumStaticColors As Integer
  82. Dim StaticColor1 As Integer
  83. Dim StaticColor2 As Integer
  84. Dim bytes() As Byte
  85. Dim wid As Long
  86. Dim hgt As Long
  87. Dim LogPal As Integer
  88. Dim palentry(0 To 255) As PALETTEENTRY
  89. ' ***********************************************
  90. ' Load the control's palette so the non-static
  91. ' colors are grays. Map the logical palette to
  92. ' match the system palette. Convert the image to
  93. ' use the non-static grays.
  94. ' Set the following module global variables.
  95. '   LogPal      Image logical palette handle.
  96. '   palentry()  Image logical palette entries.
  97. '   wid         Width of image.
  98. '   hgt         Height of image.
  99. '   bytes(1 To wid, 1 To hgt)
  100. '               Image pixel values.
  101. ' ***********************************************
  102. Sub MatchGrayPalette(pic As Control)
  103. Dim sys(0 To 255) As PALETTEENTRY
  104. Dim i As Integer
  105. Dim bm As BITMAP
  106. Dim hbm As Integer
  107. Dim status As Long
  108. Dim X As Integer
  109. Dim Y As Integer
  110. Dim gray As Single
  111. Dim dgray As Single
  112. Dim c As Integer
  113. Dim clr As Integer
  114.     ' Make sure pic has the foreground palette.
  115.     pic.ZOrder
  116.     i = RealizePalette(pic.hdc)
  117.     DoEvents
  118.     ' Get the system palette entries.
  119.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  120.         
  121.     ' Get the image pixels.
  122.     hbm = pic.Image
  123.     status = GetObject(hbm, BITMAP_SIZE, bm)
  124.     wid = bm.bmWidthBytes
  125.     hgt = bm.bmHeight
  126.     ReDim bytes(1 To wid, 1 To hgt)
  127.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  128.     ' Make the logical palette as big as possible.
  129.     LogPal = pic.Picture.hPal
  130.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  131.         Beep
  132.         MsgBox "Error resizing logical palette.", _
  133.             vbExclamation
  134.         Exit Sub
  135.     End If
  136.     ' Blank the non-static colors.
  137.     For i = 0 To StaticColor1
  138.         palentry(i) = sys(i)
  139.     Next i
  140.     For i = StaticColor1 + 1 To StaticColor2 - 1
  141.         With palentry(i)
  142.             .peRed = 0
  143.             .peGreen = 0
  144.             .peBlue = 0
  145.             .peFlags = PC_NOCOLLAPSE
  146.         End With
  147.     Next i
  148.     For i = StaticColor2 To 255
  149.         palentry(i) = sys(i)
  150.     Next i
  151.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  152.     ' Insert the non-static grays.
  153.     gray = 0
  154.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  155.     For i = StaticColor1 + 1 To StaticColor2 - 1
  156.         c = gray
  157.         gray = gray + dgray
  158.         With palentry(i)
  159.             .peRed = c
  160.             .peGreen = c
  161.             .peBlue = c
  162.         End With
  163.     Next i
  164.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  165.     ' Recreate the image using the new colors.
  166.     For Y = 1 To hgt
  167.         For X = 1 To wid
  168.             clr = bytes(X, Y)
  169.             With sys(clr)
  170.                 c = (CInt(.peRed) + .peGreen + .peBlue) / 3
  171.             End With
  172.             bytes(X, Y) = NearestNonstaticGray(c)
  173.         Next X
  174.     Next Y
  175.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  176.     ' Realize the gray palette.
  177.     i = RealizePalette(pic.hdc)
  178.     pic.Refresh
  179. End Sub
  180. ' ************************************************
  181. ' Return the index of the nonstatic color closest
  182. ' to the given color value.
  183. ' ************************************************
  184. Function NearestNonstaticColor(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer) As Integer
  185. Dim best_i As Integer
  186. Dim best_dist As Long
  187. Dim dist As Long
  188. Dim dr As Long
  189. Dim dg As Long
  190. Dim db As Long
  191. Dim i As Integer
  192.     best_dist = 1000000
  193.     For i = StaticColor1 + 1 To StaticColor2 - 1
  194.         With palentry(i)
  195.             dr = r - .peRed
  196.             dg = g - .peGreen
  197.             db = b - .peBlue
  198.             dist = dr * dr + dg * dg + db * db
  199.         End With
  200.         If best_dist > dist Then
  201.             best_i = i
  202.             best_dist = dist
  203.         End If
  204.     Next i
  205.     NearestNonstaticColor = best_i
  206. End Function
  207. ' ************************************************
  208. ' Return the index of the nonstatic gray closest
  209. ' to the given value (assuming the non-static
  210. ' colors are a gray scale created by
  211. ' MatchGrayPalette).
  212. ' ************************************************
  213. Function NearestNonstaticGray(c As Integer) As Integer
  214. Dim dgray As Single
  215.     If c < 0 Then
  216.         c = 0
  217.     ElseIf c > 255 Then
  218.         c = 255
  219.     End If
  220.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  221.     NearestNonstaticGray = c / dgray + StaticColor1 + 1
  222. End Function
  223. ' ***********************************************
  224. ' Load the control's palette so it matches the
  225. ' the system palette. Remap any of the image's
  226. ' pixels that use static colors to non-static
  227. ' colors.
  228. ' Set the following module global variables.
  229. '   LogPal      Image logical palette handle.
  230. '   palentry()  Image logical palette entries.
  231. '   wid         Width of image.
  232. '   hgt         Height of image.
  233. '   bytes(1 To wid, 1 To hgt)
  234. '               Image pixel values.
  235. ' ***********************************************
  236. Sub MatchColorPalette(pic As Control)
  237. Dim sys(0 To 255) As PALETTEENTRY
  238. Dim i As Integer
  239. Dim bm As BITMAP
  240. Dim hbm As Integer
  241. Dim status As Long
  242. Dim X As Integer
  243. Dim Y As Integer
  244. Dim clr As Integer
  245.     ' Make sure pic has the foreground palette.
  246.     pic.ZOrder
  247.     i = RealizePalette(pic.hdc)
  248.     DoEvents
  249.     ' Get the system palette entries.
  250.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  251.             
  252.     ' Make the logical palette as big as possible.
  253.     LogPal = pic.Picture.hPal
  254.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  255.         Beep
  256.         MsgBox "Error resizing logical palette.", _
  257.             vbExclamation
  258.         Exit Sub
  259.     End If
  260.     ' Blank the non-static colors.
  261.     For i = 0 To StaticColor1
  262.         palentry(i) = sys(i)
  263.     Next i
  264.     For i = StaticColor1 + 1 To StaticColor2 - 1
  265.         With palentry(i)
  266.             .peRed = 0
  267.             .peGreen = 0
  268.             .peBlue = 0
  269.             .peFlags = PC_NOCOLLAPSE
  270.         End With
  271.     Next i
  272.     For i = StaticColor2 To 255
  273.         palentry(i) = sys(i)
  274.     Next i
  275.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  276.     ' Insert the non-static colors.
  277.     For i = StaticColor1 + 1 To StaticColor2 - 1
  278.         palentry(i) = sys(i)
  279.         palentry(i).peFlags = PC_NOCOLLAPSE
  280.     Next i
  281.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  282.     ' Realize the new palette.
  283.     i = RealizePalette(pic.hdc)
  284.     ' Get the image pixels.
  285.     hbm = pic.Image
  286.     status = GetObject(hbm, BITMAP_SIZE, bm)
  287.     wid = bm.bmWidthBytes
  288.     hgt = bm.bmHeight
  289.     ReDim bytes(1 To wid, 1 To hgt)
  290.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  291.     ' Remap any pixels using static colors.
  292.     For Y = 1 To hgt
  293.         For X = 1 To wid
  294.             clr = bytes(X, Y)
  295.             If clr <= StaticColor1 Or clr >= StaticColor2 Then
  296.                 With sys(clr)
  297.                     bytes(X, Y) = _
  298.                         NearestNonstaticColor( _
  299.                         .peRed, .peGreen, .peBlue)
  300.                 End With
  301.             End If
  302.         Next X
  303.     Next Y
  304.     ' Update the image's pixel values.
  305.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  306.     pic.Refresh
  307. End Sub
  308. ' ***********************************************
  309. ' Load the indicated file and prepare to work
  310. ' with its palette.
  311. ' ***********************************************
  312. Sub LoadFromPict(fname As String)
  313. Dim status As Long
  314.     On Error GoTo LoadFileError
  315.     FromPict.Picture = LoadPicture(fname)
  316.     On Error GoTo 0
  317.         
  318.     FromHBar.Enabled = False
  319.     FromVBar.Enabled = False
  320.     DoEvents
  321.     MatchGrayPalette FromPict
  322.     FromPict.Move 0, 0
  323.     ResetScrollBars
  324.     Caption = "Make Gray [" & fname & "]"
  325.     Exit Sub
  326. LoadFileError:
  327.     Beep
  328.     MsgBox "Error loading file " & fname & "." & _
  329.         vbCrLf & Error$
  330.     Exit Sub
  331. End Sub
  332. ' ***********************************************
  333. ' Set the Max and LargeChange properties for the
  334. ' image scroll bars.
  335. ' ***********************************************
  336. Sub ResetScrollBars()
  337.     ' FromHBar.
  338.     FromHBar.Value = 0
  339.     If FromSwin.ScaleWidth >= FromPict.Width Then
  340.         FromHBar.Enabled = False
  341.     Else
  342.         FromHBar.Max = FromPict.Width - FromSwin.ScaleWidth
  343.         FromHBar.LargeChange = FromSwin.ScaleWidth
  344.         FromHBar.Enabled = True
  345.     End If
  346.     ' FromVBar.
  347.     FromVBar.Value = 0
  348.     If FromSwin.ScaleHeight >= FromPict.Height Then
  349.         FromVBar.Enabled = False
  350.     Else
  351.         FromVBar.Max = FromPict.Height - FromSwin.ScaleHeight
  352.         FromVBar.LargeChange = FromSwin.ScaleHeight
  353.         FromVBar.Enabled = True
  354.     End If
  355. End Sub
  356. ' ***********************************************
  357. ' Give the form and all the picture boxes an
  358. ' hourglass cursor.
  359. ' ***********************************************
  360. Sub WaitStart()
  361.     MousePointer = vbHourglass
  362.     FromPict.MousePointer = vbHourglass
  363.     DoEvents
  364. End Sub
  365. ' ***********************************************
  366. ' Restore the mouse pointers for the form and all
  367. ' the picture boxes.
  368. ' ***********************************************
  369. Sub WaitEnd()
  370.     MousePointer = vbDefault
  371.     FromPict.MousePointer = vbDefault
  372. End Sub
  373. Private Sub Form_Load()
  374.     ' Make sure the screen supports palettes.
  375.     If Not GetDeviceCaps(hdc, RASTERCAPS) And RC_PALETTE Then
  376.         Beep
  377.         MsgBox "This monitor does not support palettes.", _
  378.             vbCritical
  379.         End
  380.     End If
  381.     ' Get system palette size and # static colors.
  382.     SysPalSize = GetDeviceCaps(hdc, SIZEPALETTE)
  383.     NumStaticColors = GetDeviceCaps(hdc, NUMRESERVED)
  384.     StaticColor1 = NumStaticColors \ 2 - 1
  385.     StaticColor2 = SysPalSize - NumStaticColors \ 2
  386.     ' Remove the borders from FromPict.
  387.     FromPict.BorderStyle = vbTransparent
  388.     ' Make sure FromPict has control.
  389.     FromPict.ZOrder
  390. End Sub
  391. ' ***********************************************
  392. ' Make the picture as large as possible.
  393. ' ***********************************************
  394. Private Sub Form_Resize()
  395. Dim hgt As Single
  396. Dim wid As Single
  397.     If WindowState = vbMinimized Then Exit Sub
  398.         
  399.     hgt = ScaleHeight - FromHBar.Height - 1
  400.     wid = ScaleWidth - FromVBar.Width - 1
  401.     ' Place FromSwin and its scroll bars.
  402.     FromSwin.Move 0, 0, wid, hgt
  403.     FromVBar.Move _
  404.         FromSwin.Left + FromSwin.Width + 1, _
  405.         0, FromVBar.Width, hgt
  406.     FromHBar.Move _
  407.         FromSwin.Left, FromSwin.Height + 1, _
  408.         wid
  409.     ResetScrollBars
  410. End Sub
  411. Private Sub Form_Unload(Cancel As Integer)
  412.     End
  413. End Sub
  414. ' ***********************************************
  415. ' Move FromPict within FromSwin.
  416. ' ***********************************************
  417. Private Sub FromHBar_Change()
  418.     FromPict.Left = -FromHBar.Value
  419. End Sub
  420. ' ***********************************************
  421. ' Move FromPict within FromSwin.
  422. ' ***********************************************
  423. Private Sub FromHBar_Scroll()
  424.     FromPict.Left = -FromHBar.Value
  425. End Sub
  426. ' ************************************************
  427. ' Present a message indicating the pixel's palette
  428. ' index and color value.
  429. ' ************************************************
  430. Private Sub FromPict_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  431.     If X > wid Or Y > hgt Then Exit Sub
  432.     With palentry(bytes(X, Y))
  433.         MsgBox "Palette index:" & Str$(bytes(X, Y)) & _
  434.             vbCrLf & "Red:  " & Str$(.peRed) & _
  435.             vbCrLf & "Green:" & Str$(.peGreen) & _
  436.             vbCrLf & "Blue: " & Str$(.peBlue)
  437.     End With
  438. End Sub
  439. ' ***********************************************
  440. ' Load a new image file.
  441. ' ***********************************************
  442. Private Sub mnuFileLoad_Click()
  443. Dim fname As String
  444.     ' Allow the user to pick a file.
  445.     On Error Resume Next
  446.     FileDialog.filename = "*.BMP;*.ICO;*.RLE;*.WMF;*.DIB"
  447.     FileDialog.Flags = cdlOFNFileMustExist + cdlOFNHideReadOnly
  448.     FileDialog.ShowOpen
  449.     If Err.Number = cdlCancel Then
  450.         Exit Sub
  451.     ElseIf Err.Number <> 0 Then
  452.         Beep
  453.         MsgBox "Error selecting file.", , vbExclamation
  454.         Exit Sub
  455.     End If
  456.     On Error GoTo 0
  457.     fname = Trim$(FileDialog.filename)
  458.     FileDialog.InitDir = Left$(fname, Len(fname) _
  459.         - Len(FileDialog.FileTitle) - 1)
  460.     ' Load the picture.
  461.     WaitStart
  462.     DoEvents
  463.     LoadFromPict fname
  464.     WaitEnd
  465. End Sub
  466. ' ***********************************************
  467. ' End the application. (See also the QueryUnload
  468. ' event.)
  469. ' ***********************************************
  470. Private Sub mnuFileExit_Click()
  471.     Unload Me
  472. End Sub
  473. ' ***********************************************
  474. ' Move FromPict within FromSwin.
  475. ' ***********************************************
  476. Private Sub FromVBar_Change()
  477.     FromPict.Top = -FromVBar.Value
  478. End Sub
  479. ' ***********************************************
  480. ' Move FromPict within FromSwin.
  481. ' ***********************************************
  482. Private Sub FromVBar_Scroll()
  483.     FromPict.Top = -FromVBar.Value
  484. End Sub
  485.